package com.fadadianqi.starter;

import com.fadadianqi.commons.ConfigHelper;
import com.fadadianqi.commons.Constants;
import com.yeqiangwei.commons.util.StringHelper;
import com.yeqiangwei.commons.util.TypeChange;
import org.apache.log4j.Logger;
import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Handler;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.handler.ContextHandlerCollection;
import org.mortbay.jetty.handler.DefaultHandler;
import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.jetty.security.HTAccessHandler;
import org.mortbay.jetty.webapp.WebAppContext;
import org.mortbay.xml.XmlConfiguration;

import java.io.File;
import java.io.FileInputStream;
import java.net.InetAddress;

/**
 * This class starts a instance on the configured port and loads the admin
 * console web application.
 *
 * @author Sehwan Noh (devnoh@gmail.com)
 */
public class AdminConsole {

    private static final Logger log = Logger.getLogger(AdminConsole.class);

    private String adminHost;

    private int adminPort;

    private Server adminServer;

    private ContextHandlerCollection contexts;

    private boolean httpStarted = false;

    private WebAppContext context = null;

    /**
     * Constuctor that create a Jetty module.
     *
     * @param homeDir the application home directory
     */
    public AdminConsole(String homeDir) {
        String contextPath = homeDir + File.separator;
        log.info("Context path: " + contextPath);
        contexts = new ContextHandlerCollection();
        context = new WebAppContext(contexts, contextPath, "/");
        context.setWelcomeFiles(new String[]{"index.jsp"});
        //你的资源文件所在的路径 一般都在这下面
        context.setResourceBase(Constants.ROOT_PATH + "webapp");
        context.setDescriptor(Constants.ROOT_PATH + "webapp/WEB-INF/web.xml");
    }

    private boolean isAddressAvailable(String ip) {
        try {
            InetAddress address = InetAddress.getByName(ip);// ping this IP
            return address.isReachable(5000);
            /*if (address instanceof java.net.Inet4Address) {
				System.out.println(ip + " is ipv4 address");
			} else if (address instanceof java.net.Inet6Address) {
				System.out.println(ip + " is ipv6 address");
			} else {
				System.out.println(ip + " is unrecongized");
			}
			if (address.isReachable(5000)) {
				System.out.println("SUCCESS - ping " + ip
						+ " with no interface specified");
			} else {
				System.out.println("FAILURE - ping " + ip
						+ " with no interface specified");
			}
			System.out.println("\n-------Trying different interfaces--------\n");
			Enumeration<NetworkInterface> netInterfaces = NetworkInterface
					.getNetworkInterfaces();
			while (netInterfaces.hasMoreElements()) {
				NetworkInterface ni = netInterfaces.nextElement();
				System.out.println("Checking interface, DisplayName:"
						+ ni.getDisplayName() + ", Name:" + ni.getName());
				if (address.isReachable(ni, 0, 5000)) {
					System.out.println("SUCCESS - ping " + ip);
				} else {
					System.out.println("FAILURE - ping " + ip);
				}

				Enumeration<InetAddress> ips = ni.getInetAddresses();
				while (ips.hasMoreElements()) {
					System.out.println("IP: "
							+ ips.nextElement().getHostAddress());
				}
				System.out.println("-------------------------------------------");
			}*/
        } catch (Exception e) {
            System.out.println("error occurs.");
            e.printStackTrace();
        }
        return Boolean.TRUE;
    }

    /**
     * Starts the Jetty server instance.
     */
    public void startup() {
        adminHost = ConfigHelper.getString("admin.console.host", "127.0.0.1");
        adminPort = ConfigHelper.getInt("admin.console.port", 8080);
        log.info("#startup# host: " + adminHost);
        log.info("#startup# port: " + adminPort);
        adminServer = new Server();
        adminServer.setSendServerVersion(false);
        if (adminPort > 0) {
            String[] hosts = adminHost.split(",");
            for (String str : hosts) {
                String host = null;
                int port = 0;
                int i = str.indexOf(":");
                if (i != -1) {
                    host = StringHelper.substring(str, 0, i, null);
                    port = TypeChange.stringToInt(str.substring(i + 1, str.length()), adminPort);
                }
                if (!isAddressAvailable(host)) {
                    continue;
                }
                Connector httpConnector = new SelectChannelConnector();
                httpConnector.setHost(host);
                httpConnector.setPort(port);
                System.out.println("###" + host + ":" + port + "###");
                adminServer.addConnector(httpConnector);
            }
            System.out.println("###Service starts successfully！###");
        }
        if (adminServer.getConnectors() == null
                || adminServer.getConnectors().length == 0) {
            adminServer = null;
            log.warn("Admin console not started due to configuration error.");
            return;
        }
        try {

            HTAccessHandler htaccess = new HTAccessHandler();
            htaccess.setProtegee(context);

            adminServer.setHandlers(new Handler[]{contexts, htaccess, new DefaultHandler()});

            // 启动之前配置一下
            configuration();
            //
            adminServer.start();
            adminServer.join();
            httpStarted = true;
            log.info("Admin console started.");
        } catch (Exception e) {
            log.error("Could not start admin conosle server", e);
        }
    }

    private void configuration() {
        File file = new File(Constants.ROOT_PATH + "conf" + File.separator + "jetty.xml");
        if (!file.exists()) {
            log.warn("Not found " + file.getAbsolutePath());
            return;
        }
        XmlConfiguration configuration = null;
        try {
            configuration = new XmlConfiguration(new FileInputStream(file));
            configuration.configure(adminServer);
        } catch (Exception e) {
            log.error(e.toString());
        }
    }

    /**
     * Shuts down the Jetty server instance.
     */
    public void shutdown() {
        try {
            if (adminServer != null && adminServer.isRunning()) {
                adminServer.stop();
            }
        } catch (Exception e) {
            log.error("Error stopping admin console server", e);
        }
        adminServer = null;
    }

    /**
     * Restarts the Jetty server instance.
     */
    public void restart() {
        try {
            adminServer.stop();
            adminServer.start();
        } catch (Exception e) {
            log.error(e);
        }
    }

    /**
     * Returns the collection of Jetty contexts used in the admin console.
     *
     * @return the Jetty context handlers
     */
    public ContextHandlerCollection getContexts() {
        return contexts;
    }

    /**
     * Returns the host name of the admin console.
     *
     * @return the host name of the admin console.
     */
    public String getAdminHost() {
        return adminHost;
    }

    /**
     * Returns the port of the admin console.
     *
     * @return the port of the admin console.
     */
    public int getAdminPort() {
        return adminPort;
    }

    /**
     * Returns the start stutus of the admin console.
     *
     * @return true if the admin console has been started, false otherwise.
     */
    public boolean isHttpStarted() {
        return httpStarted;
    }

}
